package com.lambkit.db;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.jfinal.kit.LogKit;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.activerecord.*;
import com.lambkit.core.Lambkit;
import com.lambkit.dao.record.LambkitRecord;

import javax.sql.DataSource;
import java.util.Map;

public abstract class DataSourcePlugin implements IPlugin {

	private static Log log = LogFactory.get(DataSourcePlugin.class);

	private String configName;
	private ActiveRecordPlugin arp;

	public DataSourcePlugin(String configName) {
		this.setConfigName(configName);
	}

	public DataSourcePlugin(ActiveRecordPlugin arp) {
		this.setConfigName(arp.getConfig().getName());
		this.setArp(arp);
	}

	/**
	 * 数据源状态，0未启动，1是运行，2是睡眠
	 * @return
	 */
	public abstract int getDataSourceActiveState();

	/**
	 * 通用数据源接口获取
	 * @return
	 */
	public abstract DataSource getDataSource();

	/**
	 * 启动arp
	 * @return
	 */
	protected boolean startArp() {
		if(arp==null) {
			return false;
		}
		if (arp.getDevMode() == null) {
			arp.setDevMode(Lambkit.context().getDevMode());
		}
		if (arp.start() == false) {
			String message = "Plugin start error: " + arp.getClass().getName();
			log.error(message);
			throw new RuntimeException(message);
		}
		return true;
	}

	protected boolean stopArp() {
		if(arp==null) {
			return false;
		}
		boolean success = false;
		try {
			success = arp.stop();
		} catch (Exception e) {
			success = false;
			LogKit.error(e.getMessage(), e);
		}
		if (!success) {
			System.err.println("Plugin stop error: " + arp.getClass().getName());
		}
		return success;
	}

	public ActiveRecordPlugin getActiveRecordPlugin() {
		return this.arp;
	}

	public Config getConfig() {
		return this.arp.getConfig();
	}

	public DataSourcePlugin addMapping(String tableName, String primaryKey, Class<? extends Model<?>> modelClass, Class<? extends LambkitRecord> pojoClass) {
		if(arp!=null) {
			arp.addMapping(tableName, primaryKey, modelClass);
			//String configName = arp.getConfig().getName();
		}
		//LambkitBeanManager.me().addMapping(new TableMappingBean(configName, tableName, primaryKey, modelClass.getName(), pojoClass.getName()));
		LambkitTableMapping tableWrapper = TableMappingManager.me().addMapping(configName, tableName, primaryKey, modelClass, pojoClass);
		DataSourceManager.me().addTable(configName, tableWrapper);
		return this;
	}

	public DataSourcePlugin addMapping(String tableName, Class<? extends Model<?>> modelClass, Class<? extends LambkitRecord> pojoClass) {
		if(arp!=null) {
			arp.addMapping(tableName, modelClass);
			//String configName = arp.getConfig().getName();
		}
		//Waiting for lambkit modifications(TableMapping存储冗余)
		//LambkitBeanManager.me().addMapping(new TableMappingBean(configName, tableName, "", modelClass.getName(), pojoClass.getName()));
		LambkitTableMapping tableWrapper = TableMappingManager.me().addMapping(configName, tableName, "", modelClass, pojoClass);
		DataSourceManager.me().addTable(configName, tableWrapper);
		return this;
	}

	public DataSourcePlugin addSqlTemplate(String sqlTemplate) {
		if(arp!=null) {
			arp.addSqlTemplate(sqlTemplate);
		}
		return this;
	}

	public DataSourcePlugin addSqlTemplate(com.jfinal.template.source.ISource sqlTemplate) {
		if(arp!=null) {
			arp.addSqlTemplate(sqlTemplate);
		}
		return this;
	}

	public DataSourcePlugin setBaseSqlTemplatePath(String baseSqlTemplatePath) {
		if(arp!=null) {
			arp.setBaseSqlTemplatePath(baseSqlTemplatePath);
		}
		return this;
	}
	
	public SqlPara getSqlPara(String key, Record record) {
		return arp.getConfig().getSqlKit().getSqlPara(key, record.getColumns());
	}

	public SqlPara getSqlPara(String key, Map data) {
		return arp.getConfig().getSqlKit().getSqlPara(key, data);
	}

	public SqlPara getSqlPara(String key, Object... paras) {
		return arp.getConfig().getSqlKit().getSqlPara(key, paras);
	}

	public String getConfigName() {
		return configName;
	}

	public void setConfigName(String configName) {
		this.configName = configName;
	}

	public ActiveRecordPlugin getArp() {
		return arp;
	}

	public void setArp(ActiveRecordPlugin arp) {
		this.arp = arp;
	}

	public void setShowSql(boolean showSql) {
		if(arp!=null) {
			arp.setShowSql(showSql);
		}
	}
}
